home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 4 / Apprentice-Release4.iso / Source Code / C / Applications / µSim 1.0.5 / source / Input.c < prev    next >
Encoding:
Text File  |  1995-11-17  |  14.5 KB  |  515 lines  |  [TEXT/CWIE]

  1. /*
  2. Copyright © 1993,1994,1995 Fabrizio Oddone
  3. ••• ••• ••• ••• ••• ••• ••• ••• ••• •••
  4. This source code is distributed as freeware:
  5. you may copy, exchange, modify this code.
  6. You may include this code in any kind of application: freeware,
  7. shareware, or commercial, provided that full credits are given.
  8. You may not sell or distribute this code for profit.
  9. */
  10.  
  11. //#pragma load "MacDump"
  12.  
  13. #include    "UtilsSys7.h"
  14. #include    "CursorBalloon.h"
  15.  
  16. #include    "Globals.h"
  17. #include    "Input.h"
  18. #include    "Main.h"
  19. #include    "SimUtils.h"
  20.  
  21. //#pragma segment Main
  22.  
  23. /*    kTextMargin is the number of pixels we leave blank at the edge of the window. */
  24. enum {
  25. kTextMargin = 2,
  26.  
  27. /*    kCrChar is used to match with a carriage return when calculating the
  28.     number of lines in the TextEdit record. */
  29. kCrChar = 13,
  30.  
  31. /*    kButtonScroll is how many pixels to scroll horizontally when the button part
  32.     of the horizontal scrollbar is pressed. */
  33. kButtonScroll = 4
  34. };
  35.     
  36. /* static routines */
  37. static void GetLocalUpdateRgn(WindowPtr window, RgnHandle localRgn);
  38. static pascal void VActionProc(ControlHandle control, short part);
  39. static pascal void HActionProc(ControlHandle control, short part);
  40. static void DrawWindow(WindowPtr window);
  41. static void AdjustTE(void);
  42. static void AdjustHorz(ControlHandle control, TEHandle docTE);
  43. static void AdjustVert(ControlHandle control, TEHandle docTE);
  44. static void AdjustScrollSizes(WindowPtr window);
  45. static void AdjustScrollValues(void);
  46. static short LinesInTE(TEHandle theTE);
  47.  
  48.  
  49. void IOHome(void)
  50. {
  51. register ControlHandle    vscrollBar = gIODoc.docVScroll;
  52.  
  53. SetControlValue(vscrollBar, GetControlMinimum(vscrollBar));
  54. AdjustTE();
  55. }
  56.  
  57. void IOEnd(void)
  58. {
  59. register ControlHandle    vscrollBar = gIODoc.docVScroll;
  60.  
  61. SetControlValue(vscrollBar, GetControlMaximum(vscrollBar));
  62. AdjustTE();
  63. }
  64.  
  65. void IOPgUp(void)
  66. {
  67. VActionProc(gIODoc.docVScroll, kControlPageUpPart);
  68. }
  69.  
  70. void IOPgDn(void)
  71. {
  72. VActionProc(gIODoc.docVScroll, kControlPageDownPart);
  73. }
  74.  
  75. /*    Called when a mouseDown occurs in the grow box of an active window. In
  76.     order to eliminate any 'flicker', we want to invalidate only what is
  77.     necessary. Since ResizeWindow invalidates the whole portRect, we save
  78.     the old TE viewRect, intersect it with the new TE viewRect, and
  79.     remove the result from the update region. However, we must make sure
  80.     that any old update region that might have been around gets put back. */
  81.  
  82. void DoGrowWindow(WindowPtr window, EventRecord    *event)
  83. {
  84. Rect    tempRect;
  85. register long    growResult;
  86. register RgnHandle    tempRgn;
  87. register DocumentIOPeek doc;
  88.  
  89. if (window == gWPtr_IO) {
  90.     tempRect.right = tempRect.bottom = 0x7FFF;        /* set up limiting values */
  91.     tempRect.top = tempRect.left = kMinDocDim;
  92. /* see if it really changed size */
  93.     if (growResult = GrowWindow(window, event->where, &tempRect)) {
  94.         doc = &gIODoc;
  95.         tempRect = (*doc->docTE)->viewRect;        /* save old text box */
  96.         tempRgn = NewRgn();
  97.         GetLocalUpdateRgn(window, tempRgn);        /* get localized update region */
  98.         SizeWindow(window, LoWrd(growResult), HiWrd(growResult), true);
  99.         ResizeWindow(window);
  100. /* calculate & validate the region that hasn’t changed so it won’t get redrawn */
  101.         SectRect(&tempRect, &(*doc->docTE)->viewRect, &tempRect);
  102.         ValidRect(&tempRect);                /* take it out of update */
  103.         InvalRgn(tempRgn);                    /* put back any prior update */
  104.         DisposeRgn(tempRgn);
  105.         }
  106.     }
  107. } /* DoGrowWindow */
  108.  
  109.  
  110. /*     Called when a mouseClick occurs in the zoom box of an active window.
  111.     Everything has to get re-drawn here, so we don't mind that
  112.     ResizeWindow invalidates the whole portRect. */
  113.  
  114. void DoZoomWindow(WindowPtr window)
  115. {
  116. AdjustScrollbars(window, true);
  117. AdjustTE();
  118. } /*  DoZoomWindow */
  119.  
  120.  
  121. /* Called when the window has been resized to fix up the controls and content. */
  122.  
  123. void ResizeWindow(WindowPtr window)
  124. {
  125. InvalRect(&window->portRect);
  126. AdjustScrollbars(window, true);
  127. AdjustTE();
  128. } /* ResizeWindow */
  129.  
  130.  
  131. /* Returns the update region in local coordinates */
  132.  
  133. void GetLocalUpdateRgn(WindowPtr window, RgnHandle localRgn)
  134. {
  135. Point    mypt = { 0, 0};
  136.  
  137. LocalToGlobal(&mypt);
  138. CopyRgn(((WindowPeek) window)->updateRgn, localRgn);/* save old update region */
  139. OffsetRgn(localRgn, mypt.h, mypt.v);
  140. } /* GetLocalUpdateRgn */
  141.  
  142.  
  143. /*    This is called when an update event is received for a window.
  144.     It calls DrawWindow to draw the contents of an application window.
  145.     As an efficiency measure that does not have to be followed, it
  146.     calls the drawing routine only if the visRgn is non-empty. This
  147.     will handle situations where calculations for drawing or drawing
  148.     itself is very time-consuming. */
  149.  
  150. void DoUpdateWindow(WindowPtr window)
  151. {
  152. if (window == gWPtr_IO)
  153.     if (EmptyRgn(window->visRgn) == false)    /* draw if updating needs to be done */
  154.         DrawWindow(window);
  155. } /*DoUpdate*/
  156.  
  157.  
  158. /*    This is called when a window is activated or deactivated.
  159.     It calls TextEdit to deal with the selection. */
  160.  
  161. void DoActivateWindow(EventRecord */*evt*/, WindowPtr window, Boolean becomingActive)
  162. {
  163. Rect    growRect, tempRect;
  164. register RgnHandle    tempRgn, clipRgn;
  165. register DocumentIOPeek doc;
  166.  
  167. if (window == gWPtr_IO) {
  168.     doc = &gIODoc;
  169. /* the growbox needs to be redrawn on activation: */
  170.     growRect = window->portRect;
  171. /* adjust for the scrollbars */
  172.     growRect.top = growRect.bottom - kScrollbarAdjust + 1;
  173.     growRect.left = growRect.right - kScrollbarAdjust + 1;
  174.     if (becomingActive) {
  175. /*    since we don’t want TEActivate to draw a selection in an area where
  176.     we’re going to erase and redraw, we’ll clip out the update region
  177.     before calling it. */
  178.         tempRgn = NewRgn();
  179.         clipRgn = NewRgn();
  180.         GetLocalUpdateRgn(window, tempRgn);        /* get localized update region */
  181.         GetClip(clipRgn);
  182.         DiffRgn(clipRgn, tempRgn, tempRgn);        /* subtract updateRgn from clipRgn */
  183.         SetClip(tempRgn);
  184.         TEActivate(doc->docTE);
  185.         gTheInput = doc->docTE;
  186.         SetClip(clipRgn);                        /* restore the full-blown clipRgn */
  187.         DisposeRgn(tempRgn);
  188.         DisposeRgn(clipRgn);
  189.         InvalRect(&growRect);    /* we cannot avoid grow box flickering */
  190. /* the controls must be redrawn on activation: */
  191.         if ((*doc->docVScroll)->contrlVis == 0) {
  192.             ShowControl(doc->docVScroll);
  193.             tempRect = (*doc->docVScroll)->contrlRect;
  194.             ValidRect(&tempRect);
  195.             }
  196.         if ((*doc->docHScroll)->contrlVis == 0) {
  197.             ShowControl(doc->docHScroll);
  198.             tempRect = (*doc->docHScroll)->contrlRect;
  199.             ValidRect(&tempRect);
  200.             }
  201.         }
  202.     else {        
  203.         TEDeactivate(doc->docTE);
  204.         gTheInput = nil;
  205. /* the controls must be redrawn on deactivation: */
  206.         HideControl(doc->docVScroll);
  207.         HideControl(doc->docHScroll);
  208.         InvalRect(&growRect);
  209.         }
  210.     }
  211. } /*DoActivate*/
  212.  
  213.  
  214. /*    This is called when a mouseDown occurs in the content of a window. */
  215.  
  216. void DoContentClick(WindowPtr window, EventRecord *event)
  217. {
  218. Rect    teRect;
  219. Point    mouse;
  220. ControlHandle control;
  221. TEHandle    theTE;
  222. DocumentIOPeek doc;
  223. long    tempc;
  224. TEPtr    tPtr;
  225. short    part, value, lines;
  226.  
  227. if (window == gWPtr_IO) {
  228.     mouse = event->where;                /* get the click position */
  229.     GlobalToLocal(&mouse);
  230.     doc = &gIODoc;
  231. /* see if we are in the viewRect. if so, we won’t check the controls */
  232.     GetTERect(window, &teRect);
  233.     theTE = doc->docTE;
  234.     if (PtInRect(mouse, &teRect)) {
  235.         /* see if we need to extend the selection */
  236.         TEClick(mouse, (event->modifiers & shiftKey) != 0, theTE);
  237.         AdjustScrollValues();
  238.         }
  239.     else {
  240.         part = FindControl(mouse, window, &control);
  241.         switch ( part ) {
  242.             case 0:        /* do nothing for viewRect case */
  243.                 break;
  244.             case kControlIndicatorPart:
  245.                 value = GetControlValue(control);
  246.                 part = TrackControl(control, mouse, nil);
  247.                 if ( part ) {
  248.                     if ( control == doc->docVScroll ) {
  249.                         lines = LinesInTE(theTE);
  250.                         tPtr = *theTE;
  251.                         tempc = (lines * (long)tPtr->lineHeight) -
  252.                                 (tPtr->viewRect.bottom - tPtr->viewRect.top);
  253.                         TEPinScroll(0, tPtr->viewRect.top - tPtr->destRect.top -
  254.                             ((tempc * GetControlValue(control)) / GetControlMaximum(control)), theTE);
  255.                         }
  256.                     else
  257.                         TEPinScroll(value - GetControlValue(control), 0, theTE);
  258.                     }
  259.                 break;
  260.             default:        /* clicked in an arrow, so track & scroll */
  261.                 {
  262.                 ControlActionUPP HVActionProcUPP = NewControlActionProc(control == doc->docVScroll ? (ProcPtr)VActionProc : (ProcPtr)HActionProc);
  263.  
  264.                 (void)TrackControl(control, mouse, HVActionProcUPP);
  265.                 if (HVActionProcUPP)
  266.                     DisposeRoutineDescriptor(HVActionProcUPP);
  267.                 }
  268.                 break;
  269.             }
  270.         }
  271.     }
  272. } /*DoContentClick*/
  273.  
  274.  
  275. /* This is called for any keyDown or autoKey events, except when the
  276.  Command key is held down. It looks at the frontmost window to decide what
  277.  to do with the key typed. */
  278.  
  279. void DoKeyDown(WindowPtr window, unsigned char key, Boolean isUserInput)
  280. {
  281. if (window == gWPtr_IO) {
  282.     TEKey(key, gIODoc.docTE);
  283.     AdjustScrollbars(window, false);
  284.     if (isUserInput) {
  285.         gMMemory[kSIZE_RAM - 4] = 0;
  286.         gMMemory[kSIZE_RAM - 3] = key;
  287.         }
  288.     }
  289. } /*DoKeyDown*/
  290.  
  291. /* Determines how much to change the value of the vertical scrollbar by and how
  292.     much to scroll the TE record. */
  293.  
  294. pascal void VActionProc(ControlHandle control, short part)
  295. {
  296. register WindowPtr    window;
  297. register TEPtr        te;
  298. register short        amount;
  299.  
  300. if ( part ) {            /* if it was actually in the control */
  301.     window = (*control)->contrlOwner;
  302.     te = *gIODoc.docTE;
  303.     switch ( part ) {
  304.         case kControlUpButtonPart:
  305.             amount = te->lineHeight;
  306.             break;
  307.         case kControlDownButtonPart:
  308.             amount = - te->lineHeight;
  309.             break;
  310.         case kControlPageUpPart:
  311.             amount = te->viewRect.bottom - te->viewRect.top - te->lineHeight;
  312.             break;
  313.         case kControlPageDownPart:
  314.             amount = te->viewRect.top - te->viewRect.bottom + te->lineHeight;
  315.             break;
  316.         }
  317.     TEPinScroll(0, amount, gIODoc.docTE);
  318.     AdjustVert(control, gIODoc.docTE);
  319.     }
  320. } /* VActionProc */
  321.  
  322.  
  323. /* Determines how much to change the value of the horizontal scrollbar by and how
  324. much to scroll the TE record. */
  325.  
  326. pascal void HActionProc(ControlHandle control, short part)
  327. {
  328. register WindowPtr    window;
  329. register TEPtr        te;
  330. register short        amount;
  331.  
  332. if ( part ) {
  333.     window = (*control)->contrlOwner;
  334.     te = *gIODoc.docTE;
  335.     switch ( part ) {
  336.         case kControlUpButtonPart:
  337.             amount = kButtonScroll;
  338.             break;
  339.         case kControlDownButtonPart:
  340.             amount = - kButtonScroll;
  341.             break;
  342.         case kControlPageUpPart:
  343.             amount = te->viewRect.right - te->viewRect.left - kScrollbarAdjust;
  344.             break;
  345.         case kControlPageDownPart:
  346.             amount = te->viewRect.left - te->viewRect.right + kScrollbarAdjust;
  347.             break;
  348.         }
  349.     TEPinScroll(amount, 0, gIODoc.docTE);
  350.     AdjustHorz(control, gIODoc.docTE);
  351.     }
  352. } /* VActionProc */
  353.  
  354.  
  355. /* Draw the contents of an application window. */
  356.  
  357. void DrawWindow(WindowPtr window)
  358. {
  359. Rect    tempRect;
  360.  
  361. EraseRect(&window->portRect);
  362. tempRect = (*gIODoc.docTE)->viewRect;
  363. TEUpdate(&tempRect, gIODoc.docTE);
  364. DrawGrowIcon(window);
  365. UpdateControls(window, window->visRgn);
  366. } /*DrawWindow*/
  367.  
  368.  
  369. /* Return a rectangle that is inset from the portRect by the size of
  370.     the scrollbars and a little extra margin. */
  371.  
  372. void GetTERect(WindowPtr window, RectPtr teRect)
  373. {
  374. *teRect = window->portRect;
  375. teRect->left += kTextMargin;
  376. teRect->bottom -= kScrollbarAdjust;        /* and for the scrollbars */
  377. teRect->right -= kScrollbarAdjust;
  378. } /*GetTERect*/
  379.  
  380. /* Scroll the TERec around to match up to the potentially updated scrollbar
  381.     values. This is really useful when the window has been resized such that the
  382.     scrollbars became inactive but the TERec was already scrolled. */
  383.  
  384. void AdjustTE(void)
  385. {
  386. register TEPtr        te;
  387.  
  388. te = *gIODoc.docTE;
  389. TEPinScroll((te->viewRect.left - te->destRect.left) -
  390.         GetControlValue(gIODoc.docHScroll),
  391.         (te->viewRect.top - te->destRect.top) -
  392.             (GetControlValue(gIODoc.docVScroll) *
  393.             te->lineHeight),
  394.         gIODoc.docTE);
  395. } /*AdjustTE*/
  396.  
  397.  
  398. /* Calculate the new control maximum value and current value, whether it is the
  399. horizontal or vertical scrollbar. The vertical max is calculated by comparing the
  400. number of lines to the vertical size of the viewRect. The horizontal max is
  401. calculated by comparing the maximum document width to the width of the viewRect.
  402. The current values are set by comparing the offset between the view and
  403. destination rects. */
  404.  
  405. void AdjustHorz(ControlHandle control, TEHandle docTE)
  406. {
  407. register TEPtr    te;
  408. register short    max, min;
  409.  
  410. te = *docTE;
  411. max = (qd.screenBits.bounds.right - qd.screenBits.bounds.left) -
  412.             (te->viewRect.right - te->viewRect.left);
  413. if ( max < (min = GetControlMinimum(control)) )
  414.     max = min;
  415. SetControlMaximum(control, max);
  416. te = *docTE;    /* SetControlMaximum may move memory */
  417. SetControlValue(control, te->viewRect.left - te->destRect.left);
  418. } /*AdjustHorz*/
  419.  
  420. void AdjustVert(ControlHandle control, TEHandle docTE)
  421. {
  422. register TEPtr    te;
  423. register short    max, lines, min;
  424. long    divisor;
  425.  
  426. lines = LinesInTE(docTE);
  427. te = *docTE;
  428. max = lines - ((te->viewRect.bottom - te->viewRect.top) / te->lineHeight);
  429. if ( max < (min = GetControlMinimum(control)) ) max = min;
  430. SetControlMaximum(control, max);
  431. te = *docTE;    /* SetControlMaximum may move memory */
  432. divisor = (lines * (long)te->lineHeight) - (te->viewRect.bottom - te->viewRect.top) - (te->lineHeight >> 1);
  433. SetControlValue(control, divisor ?
  434.     (max * (long)(te->viewRect.top - te->destRect.top)) / divisor
  435.     : 0);
  436. } /*AdjustVert*/
  437.  
  438. /* Simply call the adjust routines for the vertical and horizontal scrollbars */
  439.  
  440. void AdjustScrollValues(void)
  441. {
  442. register DocumentIOPeek doc;
  443.  
  444. doc = &gIODoc;
  445. AdjustHorz(doc->docHScroll, doc->docTE);
  446. AdjustVert(doc->docVScroll, doc->docTE);
  447. } /*AdjustScrollValues*/
  448.  
  449.  
  450. /* Re-calculate the position and size of the viewRect and the scrollbars */
  451.  
  452. void AdjustScrollSizes(WindowPtr window)
  453. {
  454. Rect        teRect;
  455. register DocumentIOPeek doc;
  456.  
  457. doc = &gIODoc;
  458. GetTERect(window, &teRect);            /* start with TERect */
  459. (*doc->docTE)->viewRect = teRect;
  460. SetupVertScrollBar(window, doc->docVScroll);
  461. SetupHorzScrollBar(window, doc->docHScroll);
  462. } /*AdjustScrollSizes*/
  463.  
  464. void AdjustScrollbars(WindowPtr window, Boolean needsResize)
  465. {
  466. Rect        tempRect;
  467.  
  468. if ( needsResize ) {        /* move & size as needed */
  469.     HideControl(gIODoc.docVScroll);
  470.     HideControl(gIODoc.docHScroll);
  471.     AdjustScrollSizes(window);
  472.     }
  473. AdjustScrollValues();    /* fool with max and current value */
  474. if ( needsResize ) {                        /* move & size as needed */
  475.     ShowControl(gIODoc.docVScroll);
  476.     ShowControl(gIODoc.docHScroll);
  477.     tempRect = (*gIODoc.docVScroll)->contrlRect;
  478.     ValidRect(&tempRect);
  479.     tempRect = (*gIODoc.docHScroll)->contrlRect;
  480.     ValidRect(&tempRect);
  481.     }
  482. } /* AdjustScrollbars */
  483.  
  484. /* LinesInTE: returns the number of lines in a TextEdit field;
  485. since it calls TEGetText, it _can_ move memory */
  486.  
  487. static short LinesInTE(TEHandle theTE)
  488. {
  489. register Handle    textHand;
  490. register short    lines;
  491.  
  492. lines = (*theTE)->nLines;
  493. textHand = (Handle)TEGetText(theTE);
  494. /* since nLines isn’t right if the last character is a return, check for that case */
  495. if ( *(*textHand + InlineGetHandleSize(textHand) - 1) == kCrChar )
  496.     lines++;
  497. return(lines);
  498. }
  499.  
  500. /* procedure called when closing the IO window */
  501.  
  502. void CloseIO(WindowPtr w)
  503. {
  504. DoCloseWindow(w, kMItem_IO);
  505. }
  506.  
  507. void RecalcIO(DialogRef w, RgnBalloonCursPtr theObj)
  508. {
  509. Rect    tempRect;
  510.  
  511. GetTERect(w, &tempRect);
  512. RectRgn(theObj->zoneLocal, &tempRect);
  513. }
  514.  
  515.